package com.sskj.munite;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.DiscretePathEffect;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

public class MinuteView extends View {

    private int width;
    private int height;
    private OnIndexTouch onIndexTouch;
    private List<IMinute> data = new ArrayList<>();
    private Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Path linePath = new Path();
    private Paint shaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint touchLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private Paint touchCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    private int lineWidth = 10;
    private int num;
    private int drawNum;
    private double max;
    private double min;
    private boolean touch;
    private int lastXIntercepted;
    private int lastYIntercepted;
    private boolean isFull;

    public MinuteView(Context context) {
        super(context);
        init();
    }

    public MinuteView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        linePaint.setColor(Color.WHITE);
        linePaint.setStrokeWidth(15);
        linePaint.setTextSize(15);
        linePaint.setStyle(Paint.Style.STROKE);
        Shader mShader = new LinearGradient(0, 0, 0, 800, new int[]{Color.parseColor("#a0ffffff"), Color.parseColor("#00ffffff")}, null, Shader.TileMode.REPEAT);
        linePaint.setStyle(Paint.Style.STROKE);

        linePaint.setStrokeJoin(Paint.Join.ROUND);
        linePaint.setPathEffect(new CornerPathEffect(5));

//        linePaint.setPathEffect(new DiscretePathEffect(2,5));

        shaderPaint.setColor(Color.WHITE);
        shaderPaint.setStrokeWidth(15);
        shaderPaint.setTextSize(15);
        shaderPaint.setStyle(Paint.Style.FILL);
        shaderPaint.setShader(mShader);

        touchLinePaint.setColor(Color.WHITE);
        touchLinePaint.setTextSize(50);
        touchCirclePaint.setColor(Color.WHITE);
        touchCirclePaint.setTextSize(10);
    }

    public void setOnIndexTouch(OnIndexTouch onIndexTouch) {
        this.onIndexTouch = onIndexTouch;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        final int minimumWidth = getSuggestedMinimumWidth();
        final int minimumHeight = getSuggestedMinimumHeight();
        width = measureWidth(minimumWidth, widthMeasureSpec);
        height = measureHeight(minimumHeight, heightMeasureSpec);
        setMeasuredDimension(width, height);
    }

    private int measureWidth(int defaultWidth, int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);


        switch (specMode) {
            case MeasureSpec.EXACTLY:
                defaultWidth = specSize;
                break;
            case MeasureSpec.AT_MOST:

            case MeasureSpec.UNSPECIFIED:
                defaultWidth = Math.max(defaultWidth, specSize);
        }
        return defaultWidth;
    }


    private int measureHeight(int defaultHeight, int measureSpec) {

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {

            case MeasureSpec.EXACTLY:
                defaultHeight = specSize;
                break;
            case MeasureSpec.AT_MOST:

            case MeasureSpec.UNSPECIFIED:
                defaultHeight = Math.max(defaultHeight, specSize);

                break;
        }
        return defaultHeight;

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                touch = true;
                break;
            case MotionEvent.ACTION_MOVE:
                final int deltaX = x - lastXIntercepted;
                final int deltaY = y - lastYIntercepted;
                if (Math.abs(deltaX) < Math.abs(deltaY)) {
                    getParent().requestDisallowInterceptTouchEvent(false);
                } else {
                    getParent().requestDisallowInterceptTouchEvent(true);

                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                touch = false;
                break;

        }
        lastXIntercepted = x;
        lastYIntercepted = y;
        invalidate();
        return true;
    }


    public void updateData(List<IMinute> data) {
        if (data == null) {
            return;
        }
        this.data.clear();
        this.data.addAll(data);
        num = width / lineWidth;
        calculateFull();
        animateLine();
        invalidate();
    }

    private void animateLine() {
        drawNum = num;

//        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, num)
//                .setDuration(1000);
//        valueAnimator
//                .addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//                    @Override
//                    public void onAnimationUpdate(ValueAnimator animation) {
//                        int animatedValue = (int) animation.getAnimatedValue();
//                        drawNum=animatedValue;
//                        invalidate();
//                    }
//                });
//        valueAnimator.start();
    }

    private int getDrawNum() {
        return drawNum;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        if (data.size() <= 0) {
            return;
        }

        linePath.reset();
        calculate();
        int num = getDrawNum();
        if (isFull) {//满屏 绘制从右到左
            int start = data.size() - num;
            linePath.moveTo(0, priceToY(data.get(start).getPriceStr()));
            for (int i = start + 1; i <= data.size() - 1; i++) {
                linePath.lineTo(width - (data.size()-i) * lineWidth, priceToY(data.get(i).getPriceStr()));
//                canvas.drawLine(width - (j - 1) * lineWidth,
//                        priceToY(data.get(i + 1).getPriceStr()),
//                        width - (j) * lineWidth,
//                        priceToY(data.get(i).getPriceStr()), linePaint);
            }

            canvas.drawPath(linePath, linePaint);
            linePath.lineTo(width, height);
            linePath.lineTo(0, height);
            linePath.close();
            canvas.drawPath(linePath, shaderPaint);


        } else {//未满屏，绘制从左到右
            linePath.moveTo(0, priceToY(data.get(0).getPriceStr()));
            for (int i = 1; i < num; i++) {
                linePath.lineTo(i * lineWidth, priceToY(data.get(i).getPriceStr()));
//                canvas.drawLine(width - (j - 1) * lineWidth,
//                        priceToY(data.get(i + 1).getPriceStr()),
//                        width - (j) * lineWidth,
//                        priceToY(data.get(i).getPriceStr()), linePaint);
            }

            canvas.drawPath(linePath, linePaint);
            linePath.lineTo((num - 1) * lineWidth, height);
            linePath.lineTo(0, height);
            linePath.close();
            canvas.drawPath(linePath, shaderPaint);
        }
        if (touch && data.size() > 0) {

            int index = xToIndex(lastXIntercepted);
            if (index >= data.size()) {
                return;
            }
            if (onIndexTouch != null && index >= 0 && index < data.size()) {
                onIndexTouch.touch(data.get(index));
            } else {
                if (onIndexTouch != null) {
                    onIndexTouch.unTouch();
                }
            }
            canvas.drawLine(indexToX(index), height, indexToX(index), priceToY(data.get(index).getPriceStr()), touchLinePaint);
            canvas.drawCircle(indexToX(index), priceToY(data.get(index).getPriceStr()), 15, touchCirclePaint);
        }
    }

    private void calculateFull() {
        if (num + 1 <= data.size()) {//满屏，屏幕绘制数
            isFull = true;
            num = num + 1;
        } else {
            isFull = false;
            num = data.size();
        }
    }

    /**
     * 通过x坐标值获取最接近的数据地标
     *
     * @param x
     * @return
     */
    private int xToIndex(int x) {
        if (isFull) {
            int index = (width - x) / lineWidth;
            if ((width - x) % lineWidth > lineWidth / 2) {
                index++;
            }
            return index = data.size() - 1 - index;
        } else {
            int index = x / lineWidth;
            if (index > num) {
                index = num - 1;
            } else {
                if (x % lineWidth > lineWidth / 2) {
                    index++;
                }
            }
            return index;
        }
    }

    private float indexToX(int index) {
        if (isFull) {
            return width - (data.size() - (index + 1)) * lineWidth;
        } else {
            return lineWidth * index;
        }
    }

    private float priceToY(String price) {
        return (float) (Float.valueOf(height) - (Double.valueOf(price) - min) * height / (max - min));
    }

    private void calculate() {

        max = Double.MIN_VALUE;
        min = Double.MAX_VALUE;
        if (isFull) {
            for (int i = data.size() - 1; i >= data.size() - num - 1; i--) {
                max = Math.max(max, Double.valueOf(data.get(i).getPriceStr()));
                min = Math.min(min, Double.valueOf(data.get(i).getPriceStr()));
            }
        } else {
            for (int i = 0; i < num; i++) {
                max = Math.max(max, Double.valueOf(data.get(i).getPriceStr()));
                min = Math.min(min, Double.valueOf(data.get(i).getPriceStr()));
            }
        }
        double v = (max - min) / 10;
        max = max + v;
        min = min - v;
    }
}
